/*
 * HelloItpp.h
 *
 *  Created on: Jan 5, 2013
 *      Author: shenojia
 */

#ifndef HELLOITPP_H_
#define HELLOITPP_H_

#include <iostream>
#include <stdio.h>
#include <string>
#include <iomanip>
using namespace std;

#include <itpp\itbase.h>
#include <itpp\itcomm.h>
#include <itpp\itfixed.h>
#include <itpp\itsignal.h>
using namespace itpp;


#define FASTICA_TEST_FILE "fastica_test_data.txt"

class HelloItpp {
public:
	HelloItpp();
	virtual ~HelloItpp();
};

template <typename T>
void vec_common_operators(const Vec<T> &a, const Vec<T> &b, T c)
{
  cout.setf(ios::fixed);
  cout.precision(4);

  cout << "a = " << a << endl;
  cout << "b = " << b << endl;
  cout << "c = " << c << endl;

  cout << "a+b = " << a + b << endl;
  cout << "a+c = " << a + c << endl;
  cout << "c+a = " << c + a << endl;
  Vec<T> a2 = a;
  a2 += b;
  cout << "a+=b; a = " << a2 << endl;
  a2 = a;
  a2 += c;
  cout << "a+=c; a = " << a2 << endl;

  cout << "a-b = " << a - b << endl;
  cout << "a-c = " << a - c << endl;
  cout << "c-a = " << c - a << endl;
  a2 = a;
  a2 -= b;
  cout << "a-=b; a = " << a2 << endl;
  a2 = a;
  a2 -= c;
  cout << "a-=c; a = " << a2 << endl;
  cout << "-a = " << -a << endl;

  cout << "a*b = " << a*b << endl;
  cout << "dot(a,b) = " << dot(a, b) << endl;
  cout << "outer_product(a,b) = " << outer_product(a, b) << endl;
  cout << "a*c = " << a*c << endl;
  cout << "c*a = " << c*a << endl;
  a2 = a;
  a2 *= c;
  cout << "a*=c; a = " << a2 << endl;
  cout << "elem_mult(a,b) = " << elem_mult(a, b) << endl;
  Vec<T> x1;
  elem_mult_out(a, b, x1);
  cout << "elem_mult_out(a,b,x); x = " << x1 << endl;
  Vec<T> b2 = b;
  elem_mult_inplace(a, b2);
  cout << "elem_mult_inplace(a,b); b = " << b2 << endl;
  cout << "elem_mult_sum(a,b) = " << elem_mult_sum(a, b) << endl;

  cout << "a/c = " << a / c << endl;
  cout << "c/a = " << c / a << endl;
  a2 = a;
  a2 /= c;
  cout << "a/=c; a = " << a2 << endl;
  a2 = a;
  a2 /= b;
  cout << "a/=b; a = " << a2 << endl;
  cout << "elem_div(a,b) = " << elem_div(a, b) << endl;
  Vec<T> x2;
  elem_div_out(a, b, x2);
  cout << "elem_div_out(a,b,x); x = " << x2 << endl;
  cout << "elem_div_sum(a,b) = " << elem_div_sum(a, b) << endl;

  cout << "concat(a,b) = " << concat(a, b) << endl;
  cout << "concat(a,c) = " << concat(a, c) << endl;
  cout << "concat(c,a) = " << concat(c, a) << endl;
  cout << "concat(a,b,a) = " << concat(a, b, a) << endl;
  cout << "concat(a,b,a,b) = " << concat(a, b, a, b) << endl;
  cout << "concat(a,b,a,b,a) = " << concat(a, b, a, b, a) << endl;

  cout << "a.T() = " << a.T() << endl;
  cout << "a.H() = " << a.H() << endl;

  cout << "a.size() = " << a.size() << endl;
  a2 = a;
  a2.set_size(a2.size() + 3, true);
  cout << "a.set_size(a.size()+3, true); a = " << a2 << endl;
  a2.set_size(a2.size() - 6, true);
  cout << "a.set_size(a.size()-6, true); a = " << a2 << endl;

  cout << "a(5) = " << a(5) << endl;
  cout << "a.get(5) = " << a.get(5) << endl;
  cout << "a(0,5) = " << a(0, 5) << endl;
  cout << "a.get(0,5) = " << a.get(0, 5) << endl;
  cout << "a(6,-1) = " << a(6, -1) << endl;
  ivec idx_list = "0 5 6 7";
  cout << "idx_list = " << idx_list << endl;
  cout << "a(idx_list) = " << a(idx_list) << endl;
  cout << "a.get(idx_list) = " << a.get(idx_list) << endl;
  bvec bin_list = "1 0 0 0 0 1 1 1 0 0";
  cout << "bin_list = " << bin_list << endl;
  cout << "a(bin_list) = " << a(bin_list) << endl;
  cout << "a.get(bin_list) = " << a.get(bin_list) << endl;
  cout << "a.right(3) = " << a.right(3) << endl;
  cout << "a.left(4) = " << a.left(4) << endl;
  cout << "a.mid(3,2) = " << a.mid(3, 2) << endl;
  a2 = a;
  cout << "a.split(0) = " << a2.split(0) << ";   a = " << a2 << endl;
  a2 = a;
  cout << "a.split(a.size()) = " << a2.split(a2.size()) << ";   a = " << a2
       << endl;
  a2 = a;
  cout << "a.split(4) = " << a2.split(4) << ";   a = " << a2 << endl;
  a2(5) = a(6);
  cout << "a(5) = a(6); a = " << a2 << endl;

  a2 = a;
  a2.shift_left(c, 2);
  cout << "a.shift_left(c,2) = " << a2 << endl;
  a2 = a;
  a2.shift_right(c);
  cout << "a.shift_right(c) = " << a2 << endl;
  a2 = a;
  a2.shift_left(b.mid(0, 2));
  cout << "a.shift_left(b.mid(0,2)) = " << a2 << endl;
  a2 = a;
  a2.shift_right(b.right(5));
  cout << "a.shift_right(b.right(5)) = " << a2 << endl;

  a2 = a;
  a2.set_subvector(0, b);
  cout << "a.set_subvector(0, b) = " << a2 << endl;
  a2 = a;
  a2.set_subvector(4, b(3, 5));
  cout << "a.set_subvector(4, b(3,5)) = " << a2 << endl;
  a2 = a;
  a2.replace_mid(4, b(3, 5));
  cout << "a.replace_mid(4, b(3,5)) = " << a2 << endl;
  a2 = a;
  a2.del(6);
  cout << "a.del(6) = " << a2 << endl;
  a2 = a;
  a2.del(3, 9);
  cout << "a.del(3,9) = " << a2 << endl;
  a2 = a;
  a2.ins(0, c);
  cout << "a.ins(0,c) = " << a2 << endl;
  a2 = a;
  a2.ins(2, c);
  cout << "a.ins(2,c) = " << a2 << endl;
  a2 = a;
  a2.ins(10, c);
  cout << "a.ins(10,c) = " << a2 << endl;
  a2 = a;
  a2.ins(3, b(0, 2));
  cout << "a.ins(3, b(0,2)) = " << a2 << endl;

  a2 = a;
  a2.zeros();
  cout << "a.zeros(); a = " << a2 << endl;
  a2 = a;
  a2.ones();
  cout << "a.ones(); a = " << a2 << endl;
  a2 = a;
  a2 = c;
  cout << "a = c; a = " << a2 << endl;
  a2 = a;
  a2 = b(0, 4);
  cout << "a = b(0,4); a = " << a2 << endl;
  a2 = a;
  a2 = b.T();
  cout << "a = b.T(); a = " << a2 << endl;
  a2 = a;
  a2 = b.T().T();
  cout << "a = b.T().T(); a = " << a2 << endl << endl;
}


template <typename T>
void vec_logical_operators(const Vec<T> &a, const Vec<T> &b, T c)
{
  cout << "(a == c) = " << (a == c) << endl;
  cout << "(a != c) = " << (a != c) << endl;
  cout << "(a <= c) = " << (a <= c) << endl;
  cout << "(a >= c) = " << (a >= c) << endl;
  cout << "(a < c) = " << (a < c) << endl;
  cout << "(a > c) = " << (a > c) << endl;
  cout << "(a == b) = " << (a == b) << endl;
  cout << "(a != b) = " << (a != b) << endl;
  Vec<T> a2 = a;
  cout << "a2 = a; (a2 == a) = " << (a2 == a) << endl;
  cout << "a2 = a; (a2 != a) = " << (a2 != a) << endl << endl;
}

template <typename T>
void mat_common_operators(const Mat<T> &A, const Mat<T> &B, const Mat<T> &C,
                      const Vec<T> &u, const Vec<T> &v, T c)
{
  cout.setf(ios::fixed);
  cout.precision(4);

  cout << "A =\n" << A << endl;
  cout << "B =\n" << B << endl;
  cout << "C =\n" << C << endl;
  cout << "v = " << v << endl;
  cout << "u = " << u << endl;
  cout << "c = " << c << endl << endl;

  // indexing
  cout << "A(1,2) = " << A(1, 2) << endl;
  cout << "A(2,3) = " << A(2, 3) << endl;
  cout << "A(6) = " << A(6) << endl;
  cout << "A(0,2,1,3) =\n" << A(0, 2, 1, 3) << endl;
  cout << "A.get_row(1) = " << A.get_row(1) << endl;
  cout << "A.get_rows(1,2) =\n" << A.get_rows(1, 2) << endl;
  cout << "A.get_col(2) = " << A.get_col(2) << endl;
  cout << "A.get_cols(2,3) =\n" << A.get_cols(2, 3) << endl << endl;

  // setting, copying, swapping
  Mat<T> Mv(v);
  cout << "Mv(A) =\n" << Mv << endl;
  Mat<T> D(A);
  cout << "D(A) =\n" << D << endl;
  D.set_size(6, 5, true);
  cout << "D.set_size(6,5, true); D =\n" << D << endl;
  D.set_size(3, 2, true);
  cout << "D.set_size(3,2, true); D =\n" << D << endl;
  D.zeros();
  cout << "D.zeros(); D =\n" << D << endl;
  D.ones();
  cout << "D.ones(); D =\n" << D << endl;
  D = A;
  cout << "D = A; D =\n" << D << endl;
  D(2, 2) = c;
  cout << "D(2,2) = c; D =\n" << D << endl;
  D(9) = c;
  cout << "D(9) = c; D =\n" << D << endl;
  D.set(0, 1, c);
  cout << "D.set(0,1, c); D =\n" << D << endl;
  D.set_row(1, v);
  cout << "D.set_row(1, v); D =\n" << D << endl;
  D.set_col(2, u);
  cout << "D.set_col(2, u): D =\n" << D << endl;
  D.set_rows(0, B.get_rows(1, 2));
  cout << "D.set_rows(0, B.get_rows(1,2)); D =\n" << D << endl;
  D.set_cols(2, B.get_cols(0, 1));
  cout << "D.set_cols(2, B.get_cols(0,1)); D =\n" << D << endl;
  D.copy_row(1, 2);
  cout << "D.copy_row(1, 2); D =\n" << D << endl;
  D.copy_col(2, 3);
  cout << "D.copy_col(2, 3); D =\n" << D << endl;
  D.swap_rows(0, 2);
  cout << "D.swap_rows(0, 2); D =\n" << D << endl;
  D.swap_cols(0, 3);
  cout << "D.swap_cols(0, 3); D =\n" << D << endl;
  D.set_submatrix(1, 2, A(0, 1, 0, 1));
  cout << "D.set_submatrix(1,2, A(0,1,0,1); D =\n" << D << endl;
  D.set_submatrix(0, 0, A(0, 1, 0, 1));
  cout << "D.set_submatrix(0,0, A(0,1,0,1); D =\n" << D << endl;
  D.set_submatrix(1, 2, 2, 3, c);
  cout << "D.set_submatrix(1,2,2,3, c); D =\n" << D << endl << endl;

  // transposition
  cout << "A.T() =\n" << A.T() << endl;
  cout << "A.T().T() =\n" << A.T().T() << endl;
  cout << "A.H() =\n" << A.H() << endl << endl;

  // concatenation
  D = concat_horizontal(A, B);
  cout << "D = concat_horizontal(A,B); D =\n" << D << endl;
  D = concat_vertical(A, B);
  cout << "D = concat_vertical(A,B); D =\n" << D << endl << endl;

  // deleting rows, cols
  D.del_row(2);
  cout << "D.del_row(2); D =\n" << D << endl;
  D.del_rows(0, 2);
  cout << "D.del_rows(0,2); D =\n" << D << endl;
  D.del_col(3);
  cout << "D.del_col(3); D =\n" << D << endl;
  D.del_cols(0, 1);
  cout << "D.del_cols(0,1); D =\n" << D << endl << endl;

  // inserting, appending rows cols
  Mat<T> A2 = A;
  A2.ins_row(1, v);
  cout << "A.ins_row(1, v); A =\n" << A2 << endl;
  A2.ins_col(0, v);
  cout << "A.ins_col(0, v); A =\n" << A2 << endl;
  A2.append_col(A2.get_col(3));
  cout << "A.append_col(A2.get_col(3)); A =\n" << A2 << endl;
  A2.append_row(A2.get_row(0));
  cout << "A.append_row(A2.get_row(0)); A =\n" << A2 << endl << endl;

  // addition
  cout << "A+B =\n" << A + B << endl;
  cout << "A+c =\n" << A + c << endl;
  cout << "c+A =\n" << c + A << endl;
  A2 = A;
  A2 += B;
  cout << "A+=B; A =\n" << A2 << endl;
  A2 = A;
  A2 += c;
  cout << "A+=c; A =\n" << A2 << endl << endl;

  // subtraction
  cout << "A-B =\n" << A - B << endl;
  cout << "A-c =\n" << A - c << endl;
  cout << "c-A =\n" << c - A << endl;
  A2 = A;
  A2 -= B;
  cout << "A-=B; A =\n" << A2 << endl;
  A2 = A;
  A2 -= c;
  cout << "A-=c; A =\n" << A2 << endl;
  cout << "-A =\n" << -A << endl << endl;

  // multiplication
  cout << "A*C =\n" << A*C << endl;
  A2 = A;
  A2 *= C;
  cout << "A*=C; A =\n" << A2 << endl;
  cout << "A*c =\n" << A*c << endl;
  cout << "c*A =\n" << c*A << endl;
  A2 = A;
  A2 *= c;
  cout << "A*=c; A =\n" << A2 << endl;
  cout << "A*v = " << A*v << endl;
  cout << "elem_mult(A,B) =\n" << elem_mult(A, B) << endl;
  elem_mult_out(A, B, A2);
  cout << "elem_mult_out(A,B,out); out =\n" << A2 << endl;
  Mat<T> B2 = B;
  elem_mult_inplace(A, B2);
  cout << "elem_mult_inplace(A,B); B =\n" << B2 << endl;
  cout << "elem_mult_sum(A,B) = " << elem_mult_sum(A, B) << endl << endl;

  // division
  cout << "A/c =\n" << A / c << endl;
  A2 = A;
  A2 /= c;
  cout << "A/=c; A =\n" << A2 << endl;
  A2 = A;
  A2 /= B;
  cout << "A/=B; A =\n" << A2 << endl;
  cout << "elem_div(A,B) =\n" << elem_div(A, B) << endl;
  elem_div_out(A, B, A2);
  cout << "elem_div_out(A,B,out); out =\n" << A2 << endl;
  cout << "elem_div_sum(A,B) = " << elem_div_sum(A, B) << endl << endl;
}




#endif /* HELLOITPP_H_ */
